﻿/*
Copyright 2009 Matías Fidemraizer (www.matiasfidemraizer.com).

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

using System;
using System.Collections.Generic;

namespace Comkarl.Architecture.Patterns
{
    /// <summary>
    /// Represents the base class for a member and/or entity on some pattern implementation.
    /// </summary>
    /// <typeparam name="TIdentifierName">
    /// The type for the pattern member identifier.
    /// </typeparam>
    [Serializable]
    public abstract class PatternMember<TIdentifierName> : IEquatable<PatternMember<TIdentifierName>>
        where TIdentifierName : IEquatable<TIdentifierName>
    {
        /// <summary>
        /// Retrieves the identifier for the pattern member.
        /// </summary>
        private PatternMemberIdentifier<TIdentifierName> id;

        /// <summary>
        /// Default constructor.
        /// </summary>
        /// <param name="id">
        /// The unique identifier for the newly instantiated pattern member.
        /// </param>
        public PatternMember(PatternMemberIdentifier<TIdentifierName> id)
        {
            this.id = id;
        }

        /// <summary>
        /// Gets the identifier for the pattern member.
        /// </summary>
        public virtual PatternMemberIdentifier<TIdentifierName> ID
        {
            get { return id; }
            internal set { id = value; }
        }

        /// <summary>
        /// Overrides the equality operator.
        /// </summary>
        /// <param name="a">
        /// The left part of the equality.
        /// </param>
        /// <param name="b">
        /// The right part of the equality.
        /// </param>
        /// <returns>
        /// A boolean value which indicates that both instances are equal or not.
        /// </returns>
        public static bool operator ==(PatternMember<TIdentifierName> a, PatternMember<TIdentifierName> b)
        {
            if (ReferenceEquals(a, b))
            {
                return true;
            }

            try
            {
                return a.Equals(b);
            }
            catch(NullReferenceException)
            {
                return false;
            }
        }

        /// <summary>
        /// Overrides the negated equality operator.
        /// </summary> 
        /// <param name="a">
        /// The left part of the negated equality.
        /// </param>
        /// <param name="b">
        /// The right part of the negated equality.
        /// </param>
        /// <returns>
        /// A boolean value which indicates that both instances are equal or not.
        /// </returns>
        public static bool operator !=(PatternMember<TIdentifierName> a, PatternMember<TIdentifierName> b)
        {
            return !(a == b);
        }

        #region IEquatable<PatternMember<TIdentifierName>> Members

        public virtual bool Equals(PatternMember<TIdentifierName> other)
        {
            return other != null && ID.Equals(other.ID);
        }

        #endregion

        public override int GetHashCode()
        {
            return base.GetHashCode();
        }

        public override bool Equals(object obj)
        {
            return this == (PatternMember<TIdentifierName>)obj;
        }
    }
}
